package bma.common.langutil.jmshell.command;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import bma.common.langutil.core.StringUtil;
import bma.common.langutil.jmshell.JMShellUtil;
import bma.common.langutil.jmshell.Session;
import bma.common.langutil.jmshell.SessionCloseListener;
import bma.common.langutil.jmshell.cmdopt.CommandOptionParser;

public class WatchCommand extends AbstractSimpleCommandProcessor {

	public static final String DATA_KEY = "@watch";

	public static class WatchInfo {
		public Timer timer;
		public SessionCloseListener listener;
	}

	public WatchCommand() {
		super("watch");
		setArgsTips("[commands]");
	}

	@Override
	public CommandOptionParser createCommandOption(Session session) {
		CommandOptionParser r = new CommandOptionParser();
		r.addIntegerOption('n', "interval",
				"watch interval seconds, default 2s");
		r.addBooleanOption('s', "stop", "stop watch");
		return r;
	}

	@Override
	public boolean processCommand(Session session, String cmd,
			CommandOptionParser options) {
		boolean s = options.getOptionValue("stop", Boolean.FALSE);
		if (s) {
			stop(session);
			return true;
		}
		int n = options.getOptionValue("interval", 2);
		String[] args = options.getRemainingArgs();
		if (args != null && args.length > 0) {
			List<String> cmdlist = new ArrayList<String>();
			for (int i = 0; i < args.length; i++) {
				String commands = args[i];
				String[] cmds = StringUtil.tokenSplit(commands, ";");
				cmdlist.addAll(Arrays.asList(cmds));
			}
			set(session, cmdlist, n);
			return true;
		}
		session.writeln(getHelp(session));
		return true;
	}

	public void stop(Session s) {
		WatchInfo info = JMShellUtil.getData(s, DATA_KEY, WatchInfo.class,
				false);
		if (info != null) {
			if (info.timer != null) {
				info.timer.cancel();
				info.timer = null;
			}
		}
		s.writeln("watch stop");
	}

	public void set(final Session s, final List<String> cmdlist, int sec) {
		WatchInfo info = JMShellUtil
				.getData(s, DATA_KEY, WatchInfo.class, true);
		if (info.timer == null) {
			info.timer = new Timer();
		}
		info.timer.schedule(new TimerTask() {

			@Override
			public void run() {
				exec(s, cmdlist);
			}
		}, 0, sec * 1000);

		StringBuilder sb = new StringBuilder();
		for (String str : cmdlist) {
			if (sb.length() > 0)
				sb.append(";");
			sb.append(str);
		}
		s.writeln("watch set => " + sec + "s, " + sb.toString());

		if (info.listener != null) {
			info.listener = new SessionCloseListener() {

				@Override
				public void onClose(Session s) {
					stop(s);
				}
			};
			s.addCloseListener(info.listener);
		}
	}

	public void exec(Session s, List<String> cmdlist) {
		s.writeln("[watch]");
		for (int i = 0; i < cmdlist.size(); i++) {
			String command = cmdlist.get(i);
			s.writeln(">> " + command);
			s.execute(command);
		}
		s.writeln("[watch end]");
	}

}